//LUA script from V1.4.3 of Mapwin32
#include <windows.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include "mapwin.h"

#define ANDTMEM (65536*4)

typedef struct {	/* Structure for data blocks */
long int bgoff, fgoff;	/* offsets from start of graphic blocks */
long int fgoff2, fgoff3; /* more overlay blocks */
unsigned long int user1, user2;	/* user long data */
unsigned short int user3, user4;	/* user short data */
unsigned char user5, user6, user7;	/* user byte data */
unsigned char tl : 1;	/* bits for collision detection */
unsigned char tr : 1;
unsigned char bl : 1;
unsigned char br : 1;
unsigned char trigger : 1;	/* bit to trigger an event */
unsigned char unused1 : 1;
unsigned char unused2 : 1;
unsigned char unused3 : 1;
} BLKSTR;

typedef struct { /* Animation control structure */
signed char antype;	/* Type of anim, AN_? */
signed char andelay;	/* Frames to go before next frame */
signed char ancount;	/* Counter, decs each frame, till 0, then resets to andelay */
signed char anuser;	/* User info */
long int ancuroff;	/* Points to current offset in list */
long int anstartoff;	/* Points to start of blkstr offsets list, AFTER ref. blkstr offset */
long int anendoff;	/* Points to end of blkstr offsets list */
} ANISTR;


#define LUANUMSCRIPTS 16

#define MPY_MAPWIDTH 1		/* values for MapGetVal() */
#define MPY_MAPHEIGHT 2
#define MPY_BLOCKDEPTH 3
#define MPY_BLOCKWIDTH 4
#define MPY_BLOCKHEIGHT 5
#define MPY_NUMBLOCKSTR 6
#define MPY_NUMBLOCKGFX 7
#define MPY_BLOCKGAPX 8
#define MPY_BLOCKGAPY 9
#define MPY_BLOCKSTAGGERX 10
#define MPY_BLOCKSTAGGERY 11
#define MPY_CLICKMASK 12
#define MPY_MAPTRANS8 13
#define MPY_MAPTRANSRED 14
#define MPY_MAPTRANSGREEN 15
#define MPY_MAPTRANSBLUE 16
#define MPY_MAPCURLAYER 17
#define MPY_MAPCURBLOCK 18
#define MPY_MAPCURANIM 19
#define MPY_MAPCURBRUSH 20
#define MPY_BLKBG 21
#define MPY_BLKFG1 22
#define MPY_BLKFG2 23
#define MPY_BLKFG3 24
#define MPY_BLKUSER1 25
#define MPY_BLKUSER2 26
#define MPY_BLKUSER3 27
#define MPY_BLKUSER4 28
#define MPY_BLKUSER5 29
#define MPY_BLKUSER6 30
#define MPY_BLKUSER7 31
#define MPY_BLKFLAG1 32
#define MPY_BLKFLAG2 33
#define MPY_BLKFLAG3 34
#define MPY_BLKFLAG4 35
#define MPY_BLKFLAG5 36
#define MPY_BLKFLAG6 37
#define MPY_BLKFLAG7 38
#define MPY_BLKFLAG8 39
#define MPY_MOUSEBLOCKX 40
#define MPY_MOUSEBLOCKY 41
#define MPY_GETBLOCKMODE 42
#define MPY_NUMBLOCKANIM 43
#define ANMDELAY 44
#define ANMCOUNT 45
#define ANMTYPE 46
#define ANMUSER 47
#define ANMCURFRAME 48
#define MPY_AN_END 49
#define MPY_AN_NONE 50
#define MPY_AN_LOOPF 51
#define MPY_AN_LOOPR 52
#define MPY_AN_ONCE 53
#define MPY_AN_ONCEH 54
#define MPY_AN_PPFF 55
#define MPY_AN_PPRR 56
#define MPY_AN_PPRF 57
#define MPY_AN_PPFR 58
#define MPY_AN_ONCES 59
#define MPY_XMAPOFFSET 60
#define MPY_YMAPOFFSET 61
#define MPY_MAPFILENAME 62
#define MPY_MAPWINPATH 63
#define MPY_MAPWINVERSION 64
#define MPY_MAPTYPE 65
#define MPY_NUMBRUSHES 66
#define MPY_BRUSHWIDTH 67
#define MPY_BRUSHHEIGHT 68
#define MPY_BRUSHNAME 69
#define MPY_NUMLAYERS 70
#define MPY_ENDDEFS 71
#define MMB_OK 500
#define MMB_OKCANCEL 501
#define MMB_YESNOCANCEL 502
#define MMB_ICONNONE 503
#define MMB_ICONINFO 504
#define MMB_ICONQUESTION 505
#define MMB_ICONEXCLAMATION 506
#define MMB_CANCEL 507
#define MMB_YES 508
#define MMB_NO 509
#define MFR_OPEN 510
#define MFR_SAVE 511
#define MPY_DIALOGUE1 512
#define MPY_DIALOGUE2 513
#define MPY_DIALOGUE3 514
#define MPY_UNDO 515
#define MPY_REFFRAME 516
#define MPY_PALETTEARGB 1000

extern char mapfilename[256];
extern char defpname[256];
extern short int *brshpt[MAXBRSH];
extern char brshname[MAXBRSH][64];

extern short int mapwidth, mapheight, blockwidth, blockheight, blockdepth;
extern short int xmapoffset, ymapoffset;
extern short int numblockstr, numblockgfx, numblockanim;
extern short int curstr, curanim, curbrsh;
extern int blockgapx, blockgapy, blockstaggerx, blockstaggery, clickmask, maptype;
extern unsigned char trans16hi, trans16low, transred, transgreen, transblue, trans8bit;
extern short int * mappt;
extern char * blockstrpt;
extern char * blockgfxpt;
extern char * animstrpt;
extern unsigned char * cmappt;
extern HINSTANCE hInstance;

static lua_State * L;
static HWND lhwnd;
static char * luaplacername;
static char * luascrnames[LUANUMSCRIPTS];
static char luaactualname[64];

static const char * luadialoguetitle;
static const char * luadialoguestring;
static const char * luadialoguevalue;
static char luadialoguevalueret[256];

static int luamousex, luamousey;
static int luagetblockmode;

static int mpy_getValue (lua_State *L)
{
int i, val;
int r, g, b, a;
int retval = -1;

	val = luaL_checkint(L, 1);

	if (val >= MPY_PALETTEARGB && val < (MPY_PALETTEARGB+256)) {
		val -= MPY_PALETTEARGB;
		if (cmappt == NULL) {
			r = b = g = a = 0;
		} else {
			r = cmappt[val*3];
			g = cmappt[val*3+1];
			b = cmappt[val*3+2];
			if (val == trans8bit) a = 0; else a = 0xFF;
		}
//		retval = (a << 24) | (r << 16) | (g << 8) | b;
		lua_pushnumber (L, a);
		lua_pushnumber (L, r);
		lua_pushnumber (L, g);
		lua_pushnumber (L, b);
		return 4;
	}

	switch (luaL_checkint(L, 1)) {
		case MPY_MAPWIDTH: 
			if (mappt == NULL) retval = 0;
			else retval = (int) mapwidth;
			break;
		case MPY_MAPHEIGHT: retval = (int) mapheight; break;
		case MPY_BLOCKDEPTH: retval = (int) blockdepth; break;
		case MPY_BLOCKWIDTH: retval = (int) blockwidth; break;
		case MPY_BLOCKHEIGHT: retval = (int) blockheight; break;
		case MPY_NUMBLOCKSTR: retval = (int) numblockstr; break;
		case MPY_NUMBLOCKGFX: retval = (int) numblockgfx; break;
		case MPY_BLOCKGAPX: retval = (int) blockgapx; break;
		case MPY_BLOCKGAPY: retval = (int) blockgapy; break;
		case MPY_BLOCKSTAGGERX: retval = (int) blockstaggerx; break;
		case MPY_BLOCKSTAGGERY: retval = (int) blockstaggery; break;
		case MPY_CLICKMASK: retval = (int) clickmask; break;
		case MPY_MAPTRANS8: retval = (int) trans8bit; break;
		case MPY_MAPTRANSRED: retval = (int) transred; break;
		case MPY_MAPTRANSGREEN: retval = (int) transgreen; break;
		case MPY_MAPTRANSBLUE: retval = (int) transblue; break;
		case MPY_MAPCURLAYER: 
			for (i=0;i<8;i++) {
				if (mappt == GetLayerpt (i)) retval = i;
			}
			break;
		case MPY_MAPCURBLOCK: retval = (int) curstr; break;
		case MPY_MAPCURANIM: retval = (int) curanim; break;
		case MPY_MAPCURBRUSH: retval = (int) curbrsh-1; break;
		case MPY_MOUSEBLOCKX: retval = luamousex; break;
		case MPY_MOUSEBLOCKY: retval = luamousey; break;
		case MPY_NUMBLOCKANIM: retval = numblockanim; break;
		case MPY_XMAPOFFSET: retval = (int) xmapoffset; break;
		case MPY_YMAPOFFSET: retval = (int) ymapoffset; break;
		case MPY_MAPFILENAME: lua_pushstring (L, mapfilename); return 1;
		case MPY_MAPWINPATH: lua_pushstring (L, defpname); return 1;
		case MPY_MAPTYPE: retval = maptype; break;
		case MPY_MAPWINVERSION: retval = 143; break;
		case MPY_NUMBRUSHES:
			retval = 0;
			for (i=0;i<MAXBRSH;i++) {
				if (brshpt[i] != NULL) retval++;
			}
			break;
		case MPY_NUMLAYERS:
			retval = 0;
			for (i=0;i<8;i++) {
				if (GetLayerpt (i) != NULL) retval++;
			}
			break;
	}

	lua_pushnumber (L, retval);
	return 1;
}

static int mpy_setValue (lua_State *L)
{
int val, r, g, b;

	val = luaL_checkint(L, 1);

	if (val >= MPY_PALETTEARGB && val < (MPY_PALETTEARGB+256)) {
		r = luaL_checkint(L, 3);
		g = luaL_checkint(L, 4);
		b = luaL_checkint(L, 5);
		val -= MPY_PALETTEARGB;
		if (cmappt != NULL) {
			cmappt[val*3] = r&0xFF;
			cmappt[val*3+1] = g&0xFF;
			cmappt[val*3+2] = b&0xFF;
		}
		lua_pushnumber (L, 0);
		return 1;
	}
	switch (val) {
		case MPY_MAPTRANS8: trans8bit = luaL_checkint(L, 2); break;
		case MPY_MAPTRANSRED: transred = luaL_checkint(L, 2); break;
		case MPY_MAPTRANSGREEN: transgreen = luaL_checkint(L, 2); break;
		case MPY_MAPTRANSBLUE: transblue = luaL_checkint(L, 2); break;
		case MPY_GETBLOCKMODE: luagetblockmode = luaL_checkint(L, 2); break;
	}

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_getBlock (lua_State *L)
{
int n, x, y;
short int * mymappt;

	n = lua_gettop(L);
	x = luaL_checkint(L, 1);
	y = luaL_checkint(L, 2);
	if (n > 2) mymappt = GetLayerpt (luaL_checkint(L, 3));
	else mymappt = mappt; 

	if (mymappt == NULL) {
		sprintf (luadialoguevalueret, "getBlock: Layer %d doesn't exist", luaL_checkint(L, 3));
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
	}

	if (x < 0 || x >= mapwidth || y < 0 || y >= mapheight) {
		sprintf (luadialoguevalueret, "getBlock: Coord out of bounds %d, %d (bounds: %d, %d)", x, y, mapwidth, mapheight);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
	}

	n = (int) *(mymappt+(y*mapwidth)+x);
	if (n < 0) {
		if (luagetblockmode == 0) n /= 16;
		else {
		}
	}

//	printf ("gb: %d, %d, %d, %p, %d\n", x, y, luaL_checkint(L, 3), mymappt, n);

	lua_pushnumber (L, n);
	return 1;
}

static int mpy_setBlock (lua_State *L)
{
int n, x, y, blk;
short int * mymappt;

	n = lua_gettop(L);
	x = luaL_checkint(L, 1);
	y = luaL_checkint(L, 2);
	blk = luaL_checkint(L, 3);
	if (n > 3) mymappt = GetLayerpt (luaL_checkint(L, 4));
	else mymappt = mappt; 
//	printf ("sb: %d, %d, %d, %d, %p\n", x, y, blk, luaL_checkint(L, 4), mymappt);

	if (mymappt == NULL) {
		sprintf (luadialoguevalueret, "setBlock: Layer %d doesn't exist", luaL_checkint(L, 3));
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
	}

	if (x < 0 || x >= mapwidth || y < 0 || y >= mapheight) {
		sprintf (luadialoguevalueret, "setBlock: Coord out of bounds %d, %d (bounds: %d, %d)", x, y, mapwidth, mapheight);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
	}

	if (blk < 0) blk *= 16;
	*(mymappt+(y*mapwidth)+x) = (short int) blk;

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_getBlockValue (lua_State *L)
{
int blknum, blkval, retval;
BLKSTR * blk = (BLKSTR *) blockstrpt;
ANISTR * myanpt;
long int * templpt;

	retval = -1;

	blknum = luaL_checkint(L, 1);
	blkval = luaL_checkint(L, 2);

	if (blknum < 0) {
		myanpt = (ANISTR *) (animstrpt+ANDTMEM);
		myanpt += blknum;
		templpt = (long int *) ((animstrpt+ANDTMEM)+(myanpt->anstartoff)); templpt--;
		blknum = (*templpt)/32;
	}

	if (blknum < 0 || blknum >= numblockstr) {
		sprintf (luadialoguevalueret, "getBlockValue: block number out of bounds %d (max %d)", blknum, numblockstr-1);
		lua_pushstring (L, luadialoguevalueret);
	}

	switch (blkval) {
		case MPY_BLKBG:
			retval = blk[blknum].bgoff;
			retval /= (blockwidth*blockheight*((blockdepth+1)/8));
			break;
		case MPY_BLKFG1:
			retval = blk[blknum].fgoff;
			retval /= (blockwidth*blockheight*((blockdepth+1)/8));
			break;
		case MPY_BLKFG2:
			retval = blk[blknum].fgoff2;
			retval /= (blockwidth*blockheight*((blockdepth+1)/8));
			break;
		case MPY_BLKFG3:
			retval = blk[blknum].fgoff3;
			retval /= (blockwidth*blockheight*((blockdepth+1)/8));
			break;
		case MPY_BLKUSER1:
			retval = blk[blknum].user1;
			break;
		case MPY_BLKUSER2:
			retval = blk[blknum].user2;
			break;
		case MPY_BLKUSER3:
			retval = blk[blknum].user3;
			break;
		case MPY_BLKUSER4:
			retval = blk[blknum].user4;
			break;
		case MPY_BLKUSER5:
			retval = blk[blknum].user5;
			break;
		case MPY_BLKUSER6:
			retval = blk[blknum].user6;
			break;
		case MPY_BLKUSER7:
			retval = blk[blknum].user7;
			break;
		case MPY_BLKFLAG1:
			retval = blk[blknum].tl;
			break;
		case MPY_BLKFLAG2:
			retval = blk[blknum].tr;
			break;
		case MPY_BLKFLAG3:
			retval = blk[blknum].bl;
			break;
		case MPY_BLKFLAG4:
			retval = blk[blknum].br;
			break;
		case MPY_BLKFLAG5:
			retval = blk[blknum].trigger;
			break;
		case MPY_BLKFLAG6:
			retval = blk[blknum].unused1;
			break;
		case MPY_BLKFLAG7:
			retval = blk[blknum].unused2;
			break;
		case MPY_BLKFLAG8:
			retval = blk[blknum].unused3;
			break;
	}

	lua_pushnumber (L, retval);
	return 1;
}

static int mpy_setBlockValue (lua_State *L)
{
int blknum, blkval, newval;
BLKSTR * blk = (BLKSTR *) blockstrpt;
ANISTR * myanpt;
long int * templpt;


	blknum = luaL_checkint(L, 1);
	blkval = luaL_checkint(L, 2);
	newval = luaL_checkint(L, 3);


	if (blknum < 0) {
		myanpt = (ANISTR *) (animstrpt+ANDTMEM);
		myanpt += blknum;
		templpt = (long int *) ((animstrpt+ANDTMEM)+(myanpt->anstartoff)); templpt--;
		blknum = (*templpt)/32;
	}

	if (blknum < 0 || blknum >= numblockstr) {
		sprintf (luadialoguevalueret, "setBlockValue: block number out of bounds %d (max %d)", blknum, numblockstr-1);
		lua_pushstring (L, luadialoguevalueret);
	}

	switch (blkval) {
		case MPY_BLKBG:
			blk[blknum].bgoff = newval;
			blk[blknum].bgoff *= (blockwidth*blockheight*((blockdepth+1)/8));
			break;
		case MPY_BLKFG1:
			blk[blknum].fgoff = newval;
			blk[blknum].fgoff *= (blockwidth*blockheight*((blockdepth+1)/8));
			break;
		case MPY_BLKFG2:
			blk[blknum].fgoff2 = newval;
			blk[blknum].fgoff2 *= (blockwidth*blockheight*((blockdepth+1)/8));
			break;
		case MPY_BLKFG3:
			blk[blknum].fgoff3 = newval;
			blk[blknum].fgoff3 *= (blockwidth*blockheight*((blockdepth+1)/8));
			break;
		case MPY_BLKUSER1:
			blk[blknum].user1 = newval;
			break;
		case MPY_BLKUSER2:
			blk[blknum].user2 = newval;
			break;
		case MPY_BLKUSER3:
			blk[blknum].user3 = newval;
			break;
		case MPY_BLKUSER4:
			blk[blknum].user4 = newval;
			break;
		case MPY_BLKUSER5:
			blk[blknum].user5 = newval;
			break;
		case MPY_BLKUSER6:
			blk[blknum].user6 = newval;
			break;
		case MPY_BLKUSER7:
			blk[blknum].user7 = newval;
			break;
		case MPY_BLKFLAG1:
			blk[blknum].tl = newval;
			break;
		case MPY_BLKFLAG2:
			blk[blknum].tr = newval;
			break;
		case MPY_BLKFLAG3:
			blk[blknum].bl = newval;
			break;
		case MPY_BLKFLAG4:
			blk[blknum].br = newval;
			break;
		case MPY_BLKFLAG5:
			blk[blknum].trigger = newval;
			break;
		case MPY_BLKFLAG6:
			blk[blknum].unused1 = newval;
			break;
		case MPY_BLKFLAG7:
			blk[blknum].unused2 = newval;
			break;
		case MPY_BLKFLAG8:
			blk[blknum].unused3 = newval;
			break;
	}

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_createGraphic (lua_State *L)
{
	InsertSingleGraphic (luaL_checkint(L, 1));
	lua_pushnumber (L, luaL_checkint(L, 1));
	return 1;
}

static int mpy_deleteGraphic (lua_State *L)
{
	RemoveSingleGraphic (luaL_checkint(L, 1));
	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_createBlock (lua_State *L)
{
short int tempstr = curstr;

	curstr = luaL_checkint(L, 1);
	if (curstr <= tempstr) tempstr++;
	curstr--;
	NewBlock ();
	lua_pushnumber (L, curstr);
	curstr = tempstr;
	return 1;
}

static int mpy_deleteBlock (lua_State *L)
{
short int tempstr = curstr;

	curstr = luaL_checkint(L, 1);
	if (curstr < tempstr) tempstr--;
	CutBlock ();
	curstr = tempstr;
	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_createAnim (lua_State *L)
{
short int tempanim = curanim;

	curanim = luaL_checkint(L, 1);
	if (curanim <= tempanim) tempanim++;
	curanim--;
	AnimNew ();
	lua_pushnumber (L, curanim);
	curanim = tempanim;
	return 1;
}

static int mpy_deleteAnim (lua_State *L)
{
short int tempanim = curanim;

	curanim = luaL_checkint(L, 1);
	if (curanim < tempanim) tempanim--;
	AnimCut ();
	curanim = tempanim;
	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_getAnimFrame (lua_State *L)
{
int anum, frm, tfrms, blknum;
long int insertoff;
ANISTR * myanpt;
long int * templpt;

	anum = luaL_checkint(L, 1);
	frm = luaL_checkint(L, 2);

	if (animstrpt == NULL) {
		lua_pushstring (L, "getAnimFrame: No anims in map");
		lua_error (L);
		return 1;
	}

	if (anum < 0 || anum >= numblockanim) {
		sprintf (luadialoguevalueret, "getAnimFrame: anim number out of bounds %d (max %d)", anum, numblockanim-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	if (frm == MPY_REFFRAME) {
		myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;
		templpt = (long int *) ((animstrpt+ANDTMEM)+myanpt->anstartoff);
		templpt--;
	} else {
		myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;
		tfrms = (myanpt->anendoff - myanpt->anstartoff) / 4;
		insertoff = myanpt->anstartoff; insertoff+=(4*frm);
		templpt = (long int *) ((animstrpt+ANDTMEM)+insertoff);

		if (frm < 0 || frm >= tfrms) {
			sprintf (luadialoguevalueret, "getAnimFrame: anim frame out of bounds %d (max %d)", frm, tfrms-1);
			lua_pushstring (L, luadialoguevalueret);
			lua_error (L);
			return 1;
		}
	}

	blknum = (*templpt)/32;

	lua_pushnumber (L, blknum);
	return 1;
}

static int mpy_setAnimFrame (lua_State *L)
{
int anum, frm, tfrms, blknum;
long int insertoff;
ANISTR * myanpt;
long int * templpt;

	anum = luaL_checkint(L, 1);
	frm = luaL_checkint(L, 2);
	blknum = luaL_checkint(L, 3);

	if (animstrpt == NULL) {
		lua_pushstring (L, "setAnimFrame: No anims in map");
		lua_error (L);
		return 1;
	}

	if (anum < 0 || anum >= numblockanim) {
		sprintf (luadialoguevalueret, "setAnimFrame: anim number out of bounds %d (max %d)", anum, numblockanim-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	if (frm == MPY_REFFRAME) {
		SetRefFrame (anum, blknum);
	} else {
		myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;
		tfrms = (myanpt->anendoff - myanpt->anstartoff) / 4;
		insertoff = myanpt->anstartoff; insertoff+=(4*frm);
		templpt = (long int *) ((animstrpt+ANDTMEM)+insertoff);

		if (frm < 0 || frm >= tfrms) {
			sprintf (luadialoguevalueret, "setAnimFrame: anim frame out of bounds %d (max %d)", frm, tfrms-1);
			lua_pushstring (L, luadialoguevalueret);
			lua_error (L);
			return 1;
		}

		if (blknum < 0 || blknum >= numblockstr) {
			sprintf (luadialoguevalueret, "setAnimFrame: block number out of bounds %d (max %d)", blknum, numblockstr-1);
			lua_pushstring (L, luadialoguevalueret);
			lua_error (L);
			return 1;
		}

		*templpt = blknum*32;

	}
	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_insertAnimFrame (lua_State *L)
{
int anum, frm, tfrms, blknum;
long int insertoff;
ANISTR * myanpt;
long int * templpt;

	anum = luaL_checkint(L, 1);
	frm = luaL_checkint(L, 2);
	blknum = luaL_checkint(L, 3);

	if (animstrpt == NULL) {
		lua_pushstring (L, "setAnimFrame: No anims in map");
		lua_error (L);
		return 1;
	}

	if (anum < 0 || anum >= numblockanim) {
		sprintf (luadialoguevalueret, "setAnimFrame: anim number out of bounds %d (max %d)", anum, numblockanim-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	if (frm == MPY_REFFRAME) {
		SetRefFrame (anum, blknum);
	} else {
		myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;
		tfrms = (myanpt->anendoff - myanpt->anstartoff) / 4;
		insertoff = myanpt->anstartoff; insertoff+=(4*frm);
		templpt = (long int *) ((animstrpt+ANDTMEM)+insertoff);

		if (frm < 0 || frm > tfrms) {
			sprintf (luadialoguevalueret, "setAnimFrame: anim frame out of bounds %d (max %d)", frm, tfrms);
			lua_pushstring (L, luadialoguevalueret);
			lua_error (L);
			return 1;
		}

		if (blknum < 0 || blknum >= numblockstr) {
			sprintf (luadialoguevalueret, "setAnimFrame: block number out of bounds %d (max %d)", blknum, numblockstr-1);
			lua_pushstring (L, luadialoguevalueret);
			lua_error (L);
			return 1;
		}

		InsertAnimFrame (anum, frm, blknum);

	}
	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_cutAnimFrame (lua_State *L)
{
int anum, frm, tfrms;
long int insertoff;
ANISTR * myanpt;
long int * templpt;

	anum = luaL_checkint(L, 1);
	frm = luaL_checkint(L, 2);

	if (animstrpt == NULL) {
		lua_pushstring (L, "setAnimFrame: No anims in map");
		lua_error (L);
		return 1;
	}

	if (anum < 0 || anum >= numblockanim) {
		sprintf (luadialoguevalueret, "setAnimFrame: anim number out of bounds %d (max %d)", anum, numblockanim-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;
	tfrms = (myanpt->anendoff - myanpt->anstartoff) / 4;
	insertoff = myanpt->anstartoff; insertoff+=(4*frm);
	templpt = (long int *) ((animstrpt+ANDTMEM)+insertoff);

	if (frm < 0 || frm >= tfrms) {
		sprintf (luadialoguevalueret, "setAnimFrame: anim frame out of bounds %d (max %d)", frm, tfrms-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	DelAnimFrame (anum, frm);

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_numAnimFrames (lua_State *L)
{
int anum, i;
ANISTR * myanpt;

	anum = luaL_checkint(L, 1);

	if (animstrpt == NULL) {
		lua_pushstring (L, "setAnimFrame: No anims in map");
		lua_error (L);
		return 1;
	}

	if (anum < 0 || anum >= numblockanim) {
		sprintf (luadialoguevalueret, "numAnimFrames: anim number out of bounds %d (max %d)", anum, numblockanim-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;
	i = (myanpt->anendoff - myanpt->anstartoff) / 4;

	lua_pushnumber (L, i);
	return 1;
}

static int mpy_getAnimValue (lua_State *L)
{
int anum, afld, retval;
ANISTR * myanpt;

	anum = luaL_checkint(L, 1);
	afld = luaL_checkint(L, 2);
	retval = -1;

	if (animstrpt == NULL) {
		lua_pushstring (L, "getAnimValue: No anims in map");
		lua_error (L);
		return 1;
	}

	if (anum < 0 || anum >= numblockanim) {
		sprintf (luadialoguevalueret, "getAnimValue: anim number out of bounds %d (max %d)", anum, numblockanim-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}
	
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;

	switch (afld) {
		case ANMDELAY:
			retval = myanpt->andelay;
			break;
		case ANMCOUNT:
			retval = myanpt->ancount;
			break;
		case ANMTYPE:
			retval = myanpt->antype;
			break;
		case ANMUSER:
			retval = myanpt->anuser;
			break;
		case ANMCURFRAME:
			retval = (myanpt->ancuroff-myanpt->anstartoff)/4;
			break;
	}

	lua_pushnumber (L, retval);
	return 1;
}

static int mpy_setAnimValue (lua_State *L)
{
int anum, afld, aval;
ANISTR * myanpt;

	anum = luaL_checkint(L, 1);
	afld = luaL_checkint(L, 2);
	aval = luaL_checkint(L, 3);

	if (animstrpt == NULL) {
		lua_pushstring (L, "setAnimValue: No anims in map");
		lua_error (L);
		return 1;
	}

	if (anum < 0 || anum >= numblockanim) {
		sprintf (luadialoguevalueret, "setAnimValue: anim number out of bounds %d (max %d)", anum, numblockanim-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}
	
	myanpt = (ANISTR *) (animstrpt+ANDTMEM); myanpt -= anum; myanpt--;

	switch (afld) {
		case ANMDELAY:
			myanpt->andelay = aval;
			break;
		case ANMCOUNT:
			myanpt->ancount = aval;
			break;
		case ANMTYPE:
			myanpt->antype = aval-MPY_AN_NONE;
			break;
		case ANMUSER:
			myanpt->anuser = aval;
			break;
		case ANMCURFRAME:
			myanpt->ancuroff = myanpt->anstartoff+(aval*4);
			break;
	}

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_createBrush (lua_State *L)
{
int bnum, x, y, w, h, tbrsh;

	bnum = luaL_checkint(L, 1);
	x = luaL_checkint(L, 2);
	y = luaL_checkint(L, 3);
	w = luaL_checkint(L, 4);
	h = luaL_checkint(L, 5);

	if (bnum < 0 || bnum >= 16) {
		sprintf (luadialoguevalueret, "createBrush: brush number out of bounds %d (max 15)", bnum);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}
	
	tbrsh = curbrsh;
	curbrsh = bnum+1;
	if (MakeBrush (x, y, w, h) == 0) lua_pushnumber (L, MMB_OK);
	else lua_pushnumber (L, MMB_CANCEL);

	curbrsh = tbrsh;
	return 1;
}

static int mpy_deleteBrush (lua_State *L)
{
int bnum;

	bnum = luaL_checkint(L, 1);

	if (bnum < 0 || bnum >= 16) {
		sprintf (luadialoguevalueret, "deleteBrush: brush number out of bounds %d (max 15)", bnum);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	if (brshpt[bnum]!=NULL) { free (brshpt[bnum]); brshpt[bnum] = NULL; }
	if (curbrsh == (bnum+1)) curbrsh = 0;
	strcpy (brshname[bnum], "Brush");

	RejigBrshMenu (curbrsh);

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_renameBrush (lua_State *L)
{
int bnum;

	bnum = luaL_checkint(L, 1);

	strcpy (brshname[bnum], lua_tostring(L, 2));
	RejigBrshMenu (curbrsh);

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_getBrushBlock (lua_State *L)
{
int bnum, x, y, bw, bh;

	bnum = luaL_checkint(L, 1);
	x = luaL_checkint(L, 2);
	y = luaL_checkint(L, 3);
	
	if (bnum < 0 || bnum >= 16) {
		sprintf (luadialoguevalueret, "getBrushBlock: brush number out of bounds %d (max 15)", bnum);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	if (brshpt[bnum] == NULL) {
		sprintf (luadialoguevalueret, "getBrushBlock: brush does not exist");
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	bw = brshpt[bnum][0];
	bh = brshpt[bnum][1];
	
	if (x < 0 || x >= bw || y < 0 || y >= bh) {
		sprintf (luadialoguevalueret, "getBrushBlock: brush coords out of bounds %d, %d (max %d, %d)", x, y, bw, bh);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}
	
	lua_pushnumber (L, brshpt[bnum][2+(y*bw)+x]);
	return 1;
}

static int mpy_setBrushBlock (lua_State *L)
{
int bnum, x, y, bw, bh, bval;

	bnum = luaL_checkint(L, 1);
	x = luaL_checkint(L, 2);
	y = luaL_checkint(L, 3);
	bval = luaL_checkint(L, 4);
	
	if (bnum < 0 || bnum >= 16) {
		sprintf (luadialoguevalueret, "setBrushBlock: brush number out of bounds %d (max 15)", bnum);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	if (brshpt[bnum] == NULL) {
		sprintf (luadialoguevalueret, "setBrushBlock: brush does not exist");
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	bw = brshpt[bnum][0];
	bh = brshpt[bnum][1];
	
	if (x < 0 || x >= bw || y < 0 || y >= bh) {
		sprintf (luadialoguevalueret, "setBrushBlock: brush coords out of bounds %d,%d (max %d,%d)", x, y, bw, bh);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}
	
	brshpt[bnum][2+(y*bw)+x] = bval;

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_getBrushValue (lua_State *L)
{
int bnum, bval, retval;

	bnum = luaL_checkint(L, 1);
	bval = luaL_checkint(L, 2);

	if (bnum < 0 || bnum >= 16) {
		sprintf (luadialoguevalueret, "getBrushValue: brush number out of bounds %d (max 15)", bnum);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	if (brshpt[bnum] == NULL) {
		sprintf (luadialoguevalueret, "getBrushValue: brush does not exist");
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
		return 1;
	}

	retval = -1;

	switch (bval) {
		case MPY_BRUSHWIDTH:
			retval = brshpt[bnum][0];
			break;
		case MPY_BRUSHHEIGHT:
			retval = brshpt[bnum][1];
			break;
		case MPY_BRUSHNAME:
			lua_pushstring (L, brshname[bnum]);
			return 1;
	}
	
	lua_pushnumber (L, retval);
	return 1;
}

static int mpy_getPixel (lua_State *L)
{
int x, y, gnum;
int r, g, b, a;
unsigned char * gfxpt = (unsigned char *) blockgfxpt;

	x = luaL_checkint(L, 1);
	y = luaL_checkint(L, 2);
	gnum = luaL_checkint(L, 3);

	if (gnum < 0 || gnum >= numblockgfx) {
		sprintf (luadialoguevalueret, "getPixel: graphic number out of bounds %d, (max %d)", gnum, numblockgfx-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
	}

	if (x < 0 || x >= blockwidth || y < 0 || y >= blockheight) {
		sprintf (luadialoguevalueret, "getPixel: Coord out of bounds %d, %d (bounds: %d, %d)", x, y, blockwidth, blockheight);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
	}

	gnum *= (blockwidth*blockheight*((blockdepth+1)/8));
	gnum += (y*blockwidth*((blockdepth+1)/8));
	gnum += (x*((blockdepth+1)/8));

	switch (blockdepth) {
		case 8:
			lua_pushnumber (L, (int) gfxpt[gnum]);
			return 1;
		case 15:
			r = (gfxpt[gnum]&0xFC)<<1;
			g = (((((gfxpt[gnum])&0x3)<<3)|((gfxpt[gnum+1])>>5)))<<3;
			b = ((gfxpt[gnum+1])&0x1F)<<3;
			if (gfxpt[gnum] == trans16hi && gfxpt[gnum] == trans16low) a = 0; else a = 0xFF;
			break;
		case 16:
			r = (gfxpt[gnum]&0xF8);
			g = (((((gfxpt[gnum])&0x7)<<3)|((gfxpt[gnum+1])>>5)))<<2;
			b = ((gfxpt[gnum+1])&0x1F)<<3;
			if (gfxpt[gnum] == trans16hi && gfxpt[gnum] == trans16low) a = 0; else a = 0xFF;
			break;
		case 24:
			r = gfxpt[gnum];
			g = gfxpt[gnum+1];
			b = gfxpt[gnum+2];
			if (gfxpt[gnum] == transred && gfxpt[gnum+1] == transgreen && gfxpt[gnum+2] == transblue)
				a = 0; else a = 0xFF;
			break;
		default:
		case 32:
			r = gfxpt[gnum];
			g = gfxpt[gnum+1];
			b = gfxpt[gnum+2];
			a = gfxpt[gnum+3];
			break;
	}
	lua_pushnumber (L, a);
	lua_pushnumber (L, r);
	lua_pushnumber (L, g);
	lua_pushnumber (L, b);
	return 4;
}

static int mpy_setPixel (lua_State *L)
{
int n, x, y, gnum;
int r, g, b, a;
int c = 0;
unsigned char * gfxpt = (unsigned char *) blockgfxpt;

	n = lua_gettop(L);
	x = luaL_checkint(L, 1);
	y = luaL_checkint(L, 2);
	gnum = luaL_checkint(L, 3);
	if (n == 7) {
		a = luaL_checkint(L, 4);
		r = luaL_checkint(L, 5);
		g = luaL_checkint(L, 6);
		b = luaL_checkint(L, 7);
	} else {
		c = luaL_checkint(L, 4);
		r = (c>>16)&0xFF;
		g = (c>>8)&0xFF;
		b = c&0xFF;
		a = (c>>24)&0xFF;
	}

	if (gnum < 0 || gnum >= numblockgfx) {
		sprintf (luadialoguevalueret, "setPixel: graphic number out of bounds %d, (max %d)", gnum, numblockgfx-1);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
	}

	if (x < 0 || x >= blockwidth || y < 0 || y >= blockheight) {
		sprintf (luadialoguevalueret, "setPixel: Coord out of bounds %d, %d (bounds: %d, %d)", x, y, blockwidth, blockheight);
		lua_pushstring (L, luadialoguevalueret);
		lua_error (L);
	}

	gnum *= (blockwidth*blockheight*((blockdepth+1)/8));
	gnum += (y*blockwidth*((blockdepth+1)/8));
	gnum += (x*((blockdepth+1)/8));

	switch (blockdepth) {
		case 8:
//			printf ("gfxpt=%p, gnum=%d, c=%d\n", gfxpt, gnum, (unsigned char) (c&0xFF));
			gfxpt[gnum] = (unsigned char) (c&0xFF);
			break;
		case 15:
			gfxpt[gnum] = (r&0xF8)>>1;
			gfxpt[gnum] |= (g&0xC0)>>6;
			gfxpt[gnum+1] = (g&0x38)<<2;
			gfxpt[gnum+1] |= (b&0xF8)>>3;
			break;
		case 16:
//			printf ("gfxpt=%p, gnum=%d, c=%d\n", gfxpt, gnum, (unsigned char) (c&0xFF));
			gfxpt[gnum] = (r&0xF8);
			gfxpt[gnum] |= (g&0xE0)>>5;
			gfxpt[gnum+1] = (g&0x1C)<<3;
			gfxpt[gnum+1] |= (b&0xF8)>>3;
			break;
		case 24:
			gfxpt[gnum] = r;
			gfxpt[gnum+1] = g;
			gfxpt[gnum+2] = b;
			break;
		case 32:
			gfxpt[gnum] = a;
			gfxpt[gnum+1] = r;
			gfxpt[gnum+2] = g;
			gfxpt[gnum+3] = b;
			break;
	}
	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_msgBox (lua_State *L)
{
const char * mtitle, * mmsg;
int mtype, micon, mres, mflags;

	mtitle = lua_tostring(L, 1);
	mmsg = lua_tostring(L, 2);
	mtype = luaL_checkint(L, 3);
	micon = luaL_checkint(L, 4);

	mflags = 0;
	if (mtype == MMB_OK) mflags = MB_OK;
	if (mtype == MMB_OKCANCEL) mflags = MB_OKCANCEL;
	if (mtype == MMB_YESNOCANCEL) mflags = MB_YESNOCANCEL;
	if (micon == MMB_ICONINFO) mflags |= MB_ICONINFORMATION;
	if (micon == MMB_ICONQUESTION) mflags |= MB_ICONQUESTION;
	if (micon == MMB_ICONEXCLAMATION) mflags |= MB_ICONEXCLAMATION;

	mres = MessageBox (lhwnd, mmsg, mtitle, mflags);

	if (mres == IDOK) lua_pushnumber (L, MMB_OK);
	if (mres == IDYES) lua_pushnumber (L, MMB_YES);
	if (mres == IDNO) lua_pushnumber (L, MMB_NO);
	if (mres == IDCANCEL) lua_pushnumber (L, MMB_CANCEL);
	return 1;
}

static int mpy_fileRequester (lua_State *L)
{
int openorsave;
OPENFILENAME ofn;
char szFilter[128];
char szFile[256];
char szFileTitle[256];
char szInitDir[256];

	szFile[0] = 0; szFileTitle[0] = 0; szInitDir[0] = 0;
	strcpy (szInitDir, lua_tostring(L, 1));
	memset (szFilter, 0, sizeof (szFilter));
	strcpy (szFilter, lua_tostring(L, 2));
	strcpy (szFilter+strlen(szFilter)+1, lua_tostring(L, 3));
	memset(&ofn, 0, sizeof(OPENFILENAME));

	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = lhwnd;
	ofn.lpstrFilter = szFilter;
	ofn.nFilterIndex = 1;
	ofn.lpstrFile= szFile;
	ofn.nMaxFile = sizeof(szFile);
	ofn.lpstrFileTitle = szFileTitle;
	ofn.nMaxFileTitle = sizeof(szFileTitle);
	ofn.lpstrInitialDir = szInitDir;

	openorsave = luaL_checkint(L, 4);
	if (openorsave == MFR_OPEN) ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
	else ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;

	if (openorsave == MFR_OPEN) {
		if (GetOpenFileName(&ofn)) lua_pushnumber (L, MMB_OK);
		else lua_pushnumber (L, MMB_CANCEL);
	} else {
		if (GetSaveFileName(&ofn)) lua_pushnumber (L, MMB_OK);
		else lua_pushnumber (L, MMB_CANCEL);
	}
	lua_pushstring (L, szFile);
	return 2;
}

BOOL CALLBACK mpy_doDialogueProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg) {
		case WM_INITDIALOG:
			SetWindowText (hwndDlg, luadialoguetitle);
			SetWindowText (GetDlgItem (hwndDlg, IDC_LUADIALOGUESTRING), luadialoguestring);
			SetWindowText (GetDlgItem (hwndDlg, IDC_LUADIALOGUEVALUE), luadialoguevalue);
			break;
		case WM_COMMAND:
		switch (LOWORD(wParam))
		{
			case IDOK:
				GetWindowText (GetDlgItem (hwndDlg, IDC_LUADIALOGUEVALUE), luadialoguevalueret, sizeof(luadialoguevalueret));

				SendMessage (hwndDlg, WM_CLOSE, 0, 0L);
				break;
			case IDCANCEL:
				SendMessage (hwndDlg, WM_CLOSE, 0, -1L);
				break;
		}
		break;
		case WM_CLOSE:
			EndDialog (hwndDlg, lParam);
			break;
		default:
			return 0;
	}
	return -1;
}

static int mpy_doDialogue (lua_State *L)
{
int i, j, c;
DLGPROC dlgprc;
char tmpparam[64];

	luadialoguetitle = lua_tostring(L, 1);
	luadialoguestring = lua_tostring(L, 2);
	luadialoguevalue = lua_tostring(L, 3);
	dlgprc = (DLGPROC) MakeProcInstance (mpy_doDialogueProc, hInstance);
	i = DialogBox (hInstance, (LPCSTR) "D_LUAREQ", lhwnd, dlgprc);
	FreeProcInstance((FARPROC) dlgprc);
	if (i == 0) lua_pushnumber (L, MMB_OK);
	else lua_pushnumber (L, MMB_CANCEL);

	if (luaL_checkint(L, 4) == MPY_DIALOGUE1) {
		lua_pushstring (L, luadialoguevalueret);
		return 2;
	} else {
		i = 0; j = 0; c = 1; while (luadialoguevalueret[i] != 0) {
			if (luadialoguevalueret[i] == ',') {
				tmpparam[j] = 0;
				lua_pushstring (L, tmpparam);
				j = 0; c++;
			} else {
				tmpparam[j] = luadialoguevalueret[i];
				j++;
			}
			i++;
		}
		if (i > 0) {
			tmpparam[j] = 0;
			lua_pushstring (L, tmpparam);
			c++;
		}
		return c;
	}
}

static int mpy_shellExecute (lua_State *L)
{
int sestyle;
const char * prm1, * prm2, * prm3, * prm4;

	prm1 = lua_tostring(L, 1);
	prm2 = lua_tostring(L, 2);
	prm3 = lua_tostring(L, 3);
	prm4 = lua_tostring(L, 4);
	
	switch (luaL_checkint(L, 5)) {
		default:
			sestyle = SW_SHOW;
			break;
	}
	
	lua_pushnumber (L, (int) ShellExecute(NULL, prm1, prm2, prm3, prm4, sestyle));
	return 1;
}

static int mpy_sendMessage (lua_State *L)
{
int prm1, prm2;

	prm1 = luaL_checkint(L, 1);
	prm2 = luaL_checkint(L, 2);
	
	SendMessage (lhwnd, WM_COMMAND, prm1, prm2);
	
	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_copyLayer (lua_State *L)
{
int i, j, n;
short int * mymappt, * mymappt2;

	n = lua_gettop(L);
	i = luaL_checkint(L, 1);
	j = luaL_checkint(L, 2);

	if (i == MPY_UNDO) {
		if (j < 0 || j > 7) {
			lua_pushstring (L, "copyLayer: destination layer doesn't exist");
			lua_error (L);
		}
		mymappt = GetLayerpt (j);
		if (mymappt == NULL) {
			lua_pushstring (L, "copyLayer: destination layer doesn't exist");
			lua_error (L);
		}
		mymappt2 = mappt;
		mappt = mymappt;
		MEUndo ();
		mappt = mymappt2;
		lua_pushnumber (L, MMB_OK);
		return 1;
	}

	if (j == MPY_UNDO) {
		if (i < 0 || i > 7) {
			lua_pushstring (L, "copyLayer: source layer doesn't exist");
			lua_error (L);
		}
		mymappt = GetLayerpt (i);
		if (mymappt == NULL) {
			lua_pushstring (L, "copyLayer: source layer doesn't exist");
			lua_error (L);
		}
		mymappt2 = mappt;
		mappt = mymappt;
		MECopyToUndo ();
		mappt = mymappt2;
		lua_pushnumber (L, MMB_OK);
		return 1;
	}

	if (i < 0 || i > 7) {
		lua_pushstring (L, "copyLayer: source layer doesn't exist");
		lua_error (L);
	} else {
		if (j < 0 || j > 7) {
			lua_pushstring (L, "copyLayer: destination layer doesn't exist");
			lua_error (L);
		} else {
			mymappt = GetLayerpt (i);
			if (mymappt == NULL) {
				lua_pushstring (L, "copyLayer: source layer doesn't exist");
				lua_error (L);
			} else {
				mymappt2 = GetLayerpt (j);
				if (mymappt2 == NULL) {
					lua_pushstring (L, "copyLayer: destination layer doesn't exist");
					lua_error (L);
				} else {
					memcpy (mymappt2, mymappt, mapwidth*mapheight*2);
				}
			}
		}
	}

	lua_pushnumber (L, MMB_OK);
	return 1;
}

static int mpy_shiftVal (lua_State *L)
{
int i = luaL_checkint(L, 2);

	if (i > 0) lua_pushnumber (L, luaL_checkint(L, 1)>>i);
	else lua_pushnumber (L, luaL_checkint(L, 1)<<-i);
	return 1;
}

static int mpy_andVal (lua_State *L)
{
	lua_pushnumber (L, luaL_checkint(L, 1) & luaL_checkint(L, 2));
	return 1;
}

static int mpy_orVal (lua_State *L)
{
	lua_pushnumber (L, luaL_checkint(L, 1) | luaL_checkint(L, 2));
	return 1;
}

static int mpy_updateScreen (lua_State *L)
{
	InvalidateRgn (lhwnd, NULL, FALSE);
	lua_pushnumber (L, MMB_OK);
	return 1;
}


static const luaL_reg mpy_methods[] = {
{"getValue", mpy_getValue},
{"setValue", mpy_setValue},
{"getBlock", mpy_getBlock},
{"setBlock", mpy_setBlock},
{"getBlockValue", mpy_getBlockValue},
{"setBlockValue", mpy_setBlockValue},
{"createBlock", mpy_createBlock},
{"deleteBlock", mpy_deleteBlock},
{"createGraphic", mpy_createGraphic},
{"deleteGraphic", mpy_deleteGraphic},
{"getPixel", mpy_getPixel},
{"setPixel", mpy_setPixel},
{"msgBox",   mpy_msgBox},
{"fileRequester", mpy_fileRequester},
{"doDialogue", mpy_doDialogue},
{"shiftVal", mpy_shiftVal},
{"andVal", mpy_andVal},
{"orVal", mpy_orVal},
{"copyLayer", mpy_copyLayer},
{"updateScreen", mpy_updateScreen},
{"createAnim", mpy_createAnim},
{"deleteAnim", mpy_deleteAnim},
{"getAnimFrame", mpy_getAnimFrame},
{"setAnimFrame", mpy_setAnimFrame},
{"insertAnimFrame", mpy_insertAnimFrame},
{"cutAnimFrame", mpy_cutAnimFrame},
{"numAnimFrames", mpy_numAnimFrames},
{"getAnimValue", mpy_getAnimValue},
{"setAnimValue", mpy_setAnimValue},
{"createBrush", mpy_createBrush},
{"deleteBrush", mpy_deleteBrush},
{"renameBrush", mpy_renameBrush},
{"getBrushBlock", mpy_getBrushBlock},
{"setBrushBlock", mpy_setBrushBlock},
{"getBrushValue", mpy_getBrushValue},
{"shellExecute", mpy_shellExecute},
{"sendMessage", mpy_sendMessage},
{NULL, NULL}
};

static const char * mpy_consts[] = {
"MAPWIDTH",
"MAPHEIGHT",
"BLOCKDEPTH",
"BLOCKWIDTH",
"BLOCKHEIGHT",
"NUMBLOCKSTR",
"NUMBLOCKGFX",
"BLOCKGAPX",
"BLOCKGAPY",
"BLOCKSTAGGERX",
"BLOCKSTAGGERY",
"CLICKMASK",
"TRANS8",
"TRANSRED",
"TRANSGREEN",
"TRANSBLUE",
"CURLAYER",
"CURBLOCK",
"CURANIM",
"CURBRUSH",
"BLKBG",
"BLKFG1",
"BLKFG2",
"BLKFG3",
"BLKUSER1",
"BLKUSER2",
"BLKUSER3",
"BLKUSER4",
"BLKUSER5",
"BLKUSER6",
"BLKUSER7",
"BLKFLAG1",
"BLKFLAG2",
"BLKFLAG3",
"BLKFLAG4",
"BLKFLAG5",
"BLKFLAG6",
"BLKFLAG7",
"BLKFLAG8",
"MOUSEBLOCKX",
"MOUSEBLOCKY",
"GETBLOCKMODE",
"NUMBLOCKANIM",
"ANMDELAY",
"ANMCOUNT",
"ANMTYPE",
"ANMUSER",
"ANMCURFRAME",
"AN_END",
"AN_NONE",
"AN_LOOPF",
"AN_LOOPR",
"AN_ONCE",
"AN_ONCEH",
"AN_PPFF",
"AN_PPRR",
"AN_PPRF",
"AN_PPFR",
"AN_ONCES",
"XMAPOFFSET",
"YMAPOFFSET",
"MAPFILENAME",
"MAPWINPATH",
"MAPWINVERSION",
"MAPTYPE",
"NUMBRUSHES",
"BRUSHWIDTH",
"BRUSHHEIGHT",
"BRUSHNAME",
"NUMLAYERS"
};

static const char * mpy_consts2[] = {
"MMB_OK",
"MMB_OKCANCEL",
"MMB_YESNOCANCEL",
"MMB_ICONNONE",
"MMB_ICONINFO",
"MMB_ICONQUESTION",
"MMB_ICONEXCLAMATION",
"MMB_CANCEL",
"MMB_YES",
"MMB_NO",
"MMB_OPEN",
"MMB_SAVE",
"MMB_DIALOGUE1",
"MMB_DIALOGUE2",
"MMB_DIALOGUE3",
"MPY_UNDO",
"ANMREFFRAME"
};

//    lua_newtable(L); /* new table object */
//    lua_pushnumber(L, 0); /* userdata obj at index 0 */
//    lua_pushusertag(L, obj, otag); /* have gc call tm */
//    lua_settable(L, -2);

void LuaSetXY (int x, int y)
{
	luamousex = x; luamousey = y;
}

void LuaDoPlacer (HWND thwnd, int x, int y)
{
	lhwnd = thwnd;
	luamousex = x; luamousey = y;
	lua_dofile(L, luaplacername);
//	printf ("LuaDo %d (%s)\n", snum, luascrnames[snum]);
}

void LuaDo (HWND thwnd, int snum)
{
	lhwnd = thwnd;
	if (luascrnames[snum] != NULL) lua_dofile(L, luascrnames[snum]);
//	printf ("LuaDo %d (%s)\n", snum, luascrnames[snum]);
}

void LuaDoFile (HWND thwnd, char * lname)
{
	lhwnd = thwnd;
	lua_dofile(L, lname);
//	printf ("LuaDo %d (%s)\n", snum, luascrnames[snum]);
}

void LuaSetScript (int snum, char * sname, char * pname)
{
int i, j;

	if (luaplacername == NULL) {
		luaplacername = malloc (strlen (pname)+64);
		strcpy (luaplacername, pname);
		strcat (luaplacername, "luascr\\Placer.lua");
	}
	luascrnames[snum] = malloc (strlen (sname)+strlen (pname)+16);
	strcpy (luascrnames[snum], pname);
	strcat (luascrnames[snum], "luascr\\");
	i = strlen (luascrnames[snum]); j = 0;
	while (sname[j] >= 32) { luascrnames[snum][i] = sname[j]; i++; j++; }
	luascrnames[snum][i] = 0;
//	printf ("%s\n", luascrnames[snum]);
}

char * LuaGetScriptName (int snum)
{
int i, j;

	if (luascrnames[snum] == NULL) return "None";
	else {
		i = strlen (luascrnames[snum]); i++;
		while (luascrnames[snum][i-1] != '\\' && luascrnames[snum][i-1] != '/' && 
			luascrnames[snum][i-1] != ':' && i > 0) i--;
		j = 0; while (luascrnames[snum][i] != '.' && luascrnames[snum][i] >= ' ') {
			luaactualname[j] = luascrnames[snum][i]; i++; j++;
		}
		luaactualname[j] = 0;
		return luaactualname;
	}
}

void LuaStart (void)
{
int i;

	for (i=0;i<LUANUMSCRIPTS;i++) { luascrnames[i] = NULL; }
	luaplacername = NULL;
	luagetblockmode = 0;

	L = lua_open();

	luaopen_base(L);
	luaopen_table(L);
	luaopen_io(L);
	luaopen_string(L);
	luaopen_math(L);
	luaopen_debug(L);

	luaL_openlib(L, "mappy", mpy_methods, 0);

	for (i=1;i<MPY_ENDDEFS;i++) {
		lua_pushstring(L, mpy_consts[i-1]);
		lua_pushnumber(L, i);
		lua_rawset(L, -3);
	}
	lua_pushstring(L, "PALETTEARGB");
	lua_pushnumber(L, MPY_PALETTEARGB);
	lua_rawset(L, -3);
	for (i=0;i<=16;i++) {
		lua_pushstring(L, mpy_consts2[i]);
		lua_pushnumber(L, MMB_OK+i);
		lua_rawset(L, -3);
	}
//	LuaL_loadfile(L, "luascr\\Placer.lua")
}

void LuaStop (void)
{
int i;

	lua_close(L);
	if (luaplacername != NULL) free (luaplacername);
	for (i=0;i<LUANUMSCRIPTS;i++) {
		if (luascrnames[i] != NULL) {
			free (luascrnames[i]);
			luascrnames[i] = NULL;
		}
	}
}
